package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.common.Constants;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.common.R;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RedisKeyUtils;
import com.hmdp.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 公众号：是叶十三
 * @since 2021-12-22
 */
@Slf4j
@Service
public class UserServiceImpl extends  ServiceImpl<UserMapper, User> implements Constants, IUserService {
    @Autowired
    private UserMapper userMapper;

    @Value("${hmdp.path.domain}")
    private String domain;

    @Value("${hmdp.servlet.context-path}")
    private String contextPath;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public R sendCode(String phone, HttpSession session) {
        // 1、 校验手机号
        if (RegexUtils.isPhoneInvalid(phone)) {
            //  1.1 如何不符合直接返回错误信息
            return R.fail("手机号码无效！");
        }
        // 2、符合，生成验证码
        String code = RandomUtil.randomNumbers(6);
/*        // 3、将验证码存入session（废弃）
        session.setAttribute("code",code);*/

        // 3、将验证码存入redis，设置验证码过期时间
        String redisKey = RedisKeyUtils.getLoginCodeKey(phone);
        redisTemplate.opsForValue().set(redisKey, code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
        String v = (String)redisTemplate.opsForValue().get(redisKey);
        System.out.println(v);
        // 4、发送验证码
        // TODO 对接第三方腾讯云发送短信
        log.info("发送短信验证码成功,验证码为： {}",code);
        return R.ok();
    }

    @Override
    public R login(LoginFormDTO loginForm, HttpSession session) {
        String phone = loginForm.getPhone();
        String code = loginForm.getCode();
        /*// 缓存中的code
        String localCode = (String)session.getAttribute("code");*/
        // 从redis中取出验证码
        String codeRedisKey = RedisKeyUtils.getLoginCodeKey(phone);
        String cacheCode = (String) redisTemplate.opsForValue().get(codeRedisKey);

        // 1、手机号校验
        if (RegexUtils.isPhoneInvalid(phone)) {
            R.fail("手机号码无效！");
        }
        // 2、验证码校验
        if (cacheCode == null || cacheCode.equals("")){
            R.fail("验证码已过期，请重试！");
        }
        if (code == null || code.equals("")){
            R.fail("验证码不能为空");
        }
        if (!code.equals(cacheCode)){
            R.fail("验证码输入有误！");
        }
        // 3、判断手机号是否已经存在
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getPhone, phone);
        User user = userMapper.selectOne(lqw);
        // 4、不存在，创建新用户（自动注册功能）
        if (user == null){
            user = createUserByPhone(phone);
        }
/*        // 5、将用户保存到session
        session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));*/
        // 5、保存用户到redis中
        //  5.1 生成token，用于登录凭证
        String token = UUID.fastUUID().toString(true);
        //  5.2 将user对象转换成hash结构进行存储
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class, token);
        Map<String, Object> userDTOMap = BeanUtil.beanToMap(userDTO);
        String loginInfoRedisKey = RedisKeyUtils.getUserInfoKey(token);
        //  5.3 以token构建redisKey，存储用户信息到redis中
        redisTemplate.opsForHash().putAll(loginInfoRedisKey,userDTOMap);
        //  5.4 设置token 30分钟内有效
        redisTemplate.expire(loginInfoRedisKey, LOGIN_TOKEN_TTL,TimeUnit.MINUTES);
        //6、将token返回给浏览器
        return R.ok(token);
    }
    private User createUserByPhone(String phone){
        // 1、创建用户
        User u = new User();
        u.setPhone(phone);
        // 随机用户名
        u.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomNumbers(12));
        // 随机头像
        // http://localhost:8080/imgs/header/1.png
        u.setIcon(
                String.format(domain + "/imgs/header/%d.png", new Random().nextInt(12)));
        //保存
        int index = userMapper.insert(u);
        return u;
    }

}
